/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
  definicion de estructuras para administrar tareas
*/

#include "defines.h"
#include "gdt.h"
#include "tss.h"
#include "i386.h"

tss tarea_inicial;
tss tarea_idle;
tss tarea_dibujar;			// a.k.a. arbitro

tss tsss[CANT_TAREAS];


void tss_initializar_tarea_inicial()
{

    tsss[0] = tarea_inicial;
    
    gdt[TAREA_INICIAL_GDT_INDEX].base_0_15 = (((unsigned int) &tsss[0]) & 0xffff);
    gdt[TAREA_INICIAL_GDT_INDEX].base_23_16 = (( (unsigned int) &tsss[0]) >> 16) & 0xff;
    gdt[TAREA_INICIAL_GDT_INDEX].base_31_24 = (( (unsigned int) &tsss[0]) >> 24) & 0xff;
    gdt[TAREA_INICIAL_GDT_INDEX].limit_0_15 = (unsigned short) sizeof(tss);
}

void tss_initializar_tarea_idle()
{
	tarea_idle.cr3 = (unsigned int) KERNEL_PAGE_DIR; 			
    tarea_idle.cs = 0x8;
    tarea_idle.ds = 0x10;
    tarea_idle.ss = 0x10;
    tarea_idle.fs = 0x10;
    tarea_idle.gs = 0x10;
    tarea_idle.iomap = 0xFFFF;
    tarea_idle.eflags = 0x202;
    tarea_idle.eip = 0x3A0000; 
    tarea_idle.ebp = TASK_IDLE_STACK_RING_0 + 0x1000;
    tarea_idle.esp = TASK_IDLE_STACK_RING_0 + 0x1000;
    
    tsss[1] = tarea_idle;
    
    gdt[TAREA_IDLE_GDT_INDEX].base_0_15 	= (( (unsigned int) &tsss[1]) & 0xffff);
    gdt[TAREA_IDLE_GDT_INDEX].base_23_16	= (( (unsigned int) &tsss[1]) >> 16) & 0xff;
    gdt[TAREA_IDLE_GDT_INDEX].base_31_24 	= (( (unsigned int) &tsss[1]) >> 24) & 0xff;
    gdt[TAREA_IDLE_GDT_INDEX].limit_0_15 	= (unsigned short) sizeof(tss);
}

void tss_inicializar_arbitro() {
    int indice_tss = 6;
    
	tsss[indice_tss].cr3 = TASK_5_PAGE_DIR; 			
    tsss[indice_tss].cs = 0x1A;
    tsss[indice_tss].ds = 0x22;
    tsss[indice_tss].ss = 0x22;
    tsss[indice_tss].fs = 0x22;
    tsss[indice_tss].gs = 0x22;
    tsss[indice_tss].es = 0x22;
    tsss[indice_tss].iomap = 0xFFFF;
    
    tsss[indice_tss].ss0 = 0x10;
    
    tsss[indice_tss].eflags = 0x202;
    tsss[indice_tss].eip = TASK_CODE; 
    tsss[indice_tss].ebp = TASK_STACK + 0x1000;
    tsss[indice_tss].esp = TASK_STACK + 0x1000;
    tsss[indice_tss].esp0 = TASK_5_STACK_RING_0 + 0x1000;
    
    unsigned int task_gdt_index = TAREA_5_GDT_INDEX;
    gdt[task_gdt_index].base_0_15 	= (( (unsigned int) &tsss[indice_tss]) & 0xffff);
    gdt[task_gdt_index].base_23_16	= (( (unsigned int) &tsss[indice_tss]) >> 16) & 0xff;
    gdt[task_gdt_index].base_31_24 	= (( (unsigned int) &tsss[indice_tss]) >> 24) & 0xff;
    gdt[task_gdt_index].limit_0_15 	= (unsigned short) sizeof(tss);

}

void tss_inicializar_tarea(unsigned int numero_tarea, 
                            unsigned int task_page_dir,
                            unsigned int task_stack_ring_0,
                            unsigned int task_gdt_index)
{
    int indice_tss = 1 + numero_tarea;
    
	tsss[indice_tss].cr3 = task_page_dir; 			
    tsss[indice_tss].cs = 0x2B;
    tsss[indice_tss].ds = 0x33;
    tsss[indice_tss].ss = 0x33;
    tsss[indice_tss].fs = 0x33;
    tsss[indice_tss].gs = 0x33;
    tsss[indice_tss].es = 0x33;
    tsss[indice_tss].iomap = 0xFFFF;
    
    tsss[indice_tss].ss0 = 0x10;
    
    tsss[indice_tss].eflags = 0x202;
    tsss[indice_tss].eip = TASK_CODE; 
    tsss[indice_tss].ebp = TASK_STACK + 0x1000;
    tsss[indice_tss].esp = TASK_STACK + 0x1000;
    tsss[indice_tss].esp0 = task_stack_ring_0 + 0x1000;
    
    
    gdt[task_gdt_index].base_0_15 	= (( (unsigned int) &tsss[indice_tss]) & 0xffff);
    gdt[task_gdt_index].base_23_16	= (( (unsigned int) &tsss[indice_tss]) >> 16) & 0xff;
    gdt[task_gdt_index].base_31_24 	= (( (unsigned int) &tsss[indice_tss]) >> 24) & 0xff;
    gdt[task_gdt_index].limit_0_15 	= (unsigned short) sizeof(tss);
}

void tss_inicializar()
{
	tss_initializar_tarea_inicial();
    tss_initializar_tarea_idle();
    
    tss_inicializar_tarea(1, TASK_1_PAGE_DIR, TASK_1_STACK_RING_0, TAREA_1_GDT_INDEX);
    tss_inicializar_tarea(2, TASK_2_PAGE_DIR, TASK_2_STACK_RING_0, TAREA_2_GDT_INDEX);
    tss_inicializar_tarea(3, TASK_3_PAGE_DIR, TASK_3_STACK_RING_0, TAREA_3_GDT_INDEX);
    tss_inicializar_tarea(4, TASK_4_PAGE_DIR, TASK_4_STACK_RING_0, TAREA_4_GDT_INDEX);
    
    tss_inicializar_arbitro();
    
}
